import random
from controller import Graz
from controller import Stimulator
from Processor import Processor
from controller.OpenViBEStim import OpenViBEStimulation


def mi_stimulator(config_data, stim_callback):
    simulator = Stimulator(stim_callback)
    tasks = []
    tasks += ['OVTK_GDF_Left'] * int(config_data.cueSetting['firstClassNum'])
    tasks += ['OVTK_GDF_Right'] * int(config_data.cueSetting['secondClassNum'])
    random.shuffle(tasks)
    display_cue_duration = int(config_data.cueSetting['dispCueDuration'])
    iter = config_data.cueSetting['repeatCue']
    one_cue_time = int(1 / (2 * iter) * display_cue_duration)
    simulator.add_stim('OVTK_StimulationId_ExperimentStart', config_data.cueSetting['baselineDuration'])  # 32769
    for task in tasks:
        simulator.add_stim('OVTK_GDF_Start_Of_Trial', 1)  # 768
        if task == 'OVTK_GDF_Left':
            for i in range(iter):
                simulator.add_stim('OVTK_GDF_Left', one_cue_time)  # 769 move-down
                simulator.add_stim('OVTK_GDF_class5', one_cue_time)  # 773 move-up
        else:
            simulator.add_stim('OVTK_GDF_Right', display_cue_duration)  # 770
        simulator.add_stim('OVTK_GDF_End_Of_Trial', int(config_data.cueSetting['waitCueDuration']))  # 800
    simulator.add_stim('OVTK_StimulationId_ExperimentStop')  # 32770
    return simulator


class MIController(object):
    def __init__(self, config_data, is_online):
        self.is_online = is_online
        self.stimulator = mi_stimulator(config_data, self.on_stim)
        self.processor = Processor(is_online, config_data, self.stimulator, self)
        self.graz = Graz(self.stimulator, config_data)

    def start(self):
        self.graz.start_stim(self.is_online)
        self.processor.start()

    def on_stim(self, stim):
        if stim is None:
            self.stop()
            return
        self.graz.on_stim(stim)
        code = OpenViBEStimulation.get(stim, -1)
        if code != -1:
            self.processor.change_mark(code)

    def stop(self):
        self.processor.stop()
